package org.hy.common.ui;

import java.awt.LayoutManager;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

import javax.swing.JPanel;
import javax.swing.JScrollBar;

import org.hy.common.Date;
import org.hy.common.ui.event.TimeChangeEvent;
import org.hy.common.ui.event.TimeChangeListener;





/**
 * 时刻面板(HH24:MI:SS)。
 *
 * @author   ZhengWei(HY)
 * @version  V1.0  2012-04-01
 */
public final class JTimePanel extends JPanel
{
    private static final long serialVersionUID = -9077361128741026787L;
    
    /** 小时 */
    private int                             hour;
    
    /** 分钟 */
    private int                             minute;
    
    /** 秒 */
    private int                             second;
    
    /** 显示时刻的文本框 */
    private JTextField                      jtTime;
    
    /** 小时调节器 */
    private JScrollBar                      jsHour;
    
    /** 分钟调节器 */
    private JScrollBar                      jsMinute;
    
    /** 秒钟调节器 */
    private JScrollBar                      jsSecond;
    
    /**
     * 是否允许事件。内部参数不对外开放。
     * 当由内部发起的，对控件的改变时，即不发起事件。
     */
    private boolean                         isAllowEvent;
    
    /** 自定义事件的监听器集合 */
    private Collection<TimeChangeListener>  listeners;
    
    
    
    public JTimePanel()
    {
        super();
        
        this.init();
        this.setValue(0 ,0 ,0);
    }
    
    
    
    public JTimePanel(java.util.Date i_Date)
    {
        this(new Date(i_Date));
    }
    
    
    
    public JTimePanel(Date i_Date)
    {
        super();
        
        this.init();
        this.setValue(i_Date);
    }
    
    
    
    public JTimePanel(boolean isDoubleBuffered)
    {
        super(isDoubleBuffered);
        
        this.init();
        this.setValue(0 ,0 ,0);
    }
    
    
    
    public JTimePanel(LayoutManager layout)
    {
        super(layout);
        
        this.init();
        this.setValue(0 ,0 ,0);
    }
    
    
    
    public JTimePanel(LayoutManager layout, boolean isDoubleBuffered)
    {
        super(layout, isDoubleBuffered);
        
        this.init();
        this.setValue(0 ,0 ,0);
    }
    
    
    
    /**
     * 注册事件
     * 
     * @param e
     */
    public void addTimeChangeListener(TimeChangeListener e)
    {
        if ( this.listeners == null )
        {
            this.listeners = new HashSet<TimeChangeListener>();
        }
        
        this.listeners.add(e);
    }
    
    
    
    /**
     * 移除事件
     * 
     * @param e
     */
    public void removeTimeChangeListener(TimeChangeListener e)
    {
        if ( this.listeners == null )
        {
            return;
        }
        
        this.listeners.remove(e);
    }
    
    
    
    /**
     * 触发日期值改变事件
     * 
     * @param i_Date
     */
    protected void fireTimeChange()
    {
        if ( this.listeners == null )
        {
            return;
        }
        
        TimeChangeEvent v_Event = new TimeChangeEvent(this ,this.hour ,this.minute ,this.second);
        
        notifyListeners(v_Event);
    }
    
    
    
    /**
     * 通知所有注册事件监听的对象
     * 
     * @param i_Event
     */
    private void notifyListeners(TimeChangeEvent i_Event)
    {
        Iterator<TimeChangeListener> v_Iter = this.listeners.iterator();

        while ( v_Iter.hasNext() )
        {
            TimeChangeListener v_Listener = v_Iter.next();

            v_Listener.onChangeListener(i_Event);
        }
    }
    
    
    
    /**
     * 初始化
     */
    private void init()
    {
        this.jtTime   = new JTextField(" 00  :  00  :  00 ");
        this.jsHour   = new JScrollBar();
        this.jsMinute = new JScrollBar();
        this.jsSecond = new JScrollBar();
        
        
        this.jtTime.setEditable(false);
        
        
        this.jsHour  .setMinimum(-1);
        this.jsMinute.setMinimum(-1);
        this.jsSecond.setMinimum(-1);
        
        
        this.jsHour.setMaximum(25);
        this.jsMinute.setMaximum(61);
        this.jsSecond.setMaximum(61);
        
        
        this.jsHour  .setVisibleAmount(1);
        this.jsMinute.setVisibleAmount(1);
        this.jsSecond.setVisibleAmount(1);
        
        
        this.jsHour  .setOrientation(JScrollBar.HORIZONTAL);
        this.jsMinute.setOrientation(JScrollBar.HORIZONTAL);
        this.jsSecond.setOrientation(JScrollBar.HORIZONTAL);
        
        
        
        // 布局
        int v_MyWidth = 82;
        this.jtTime  .setBounds(0  ,0  ,v_MyWidth ,20);
        this.jsHour  .setBounds(2  ,22 ,20 ,14);
        this.jsMinute.setBounds(this.jsHour.getX()   + this.jsHour.getWidth()   + 8 ,this.jsHour.getY() ,this.jsHour.getWidth() ,this.jsHour.getHeight());
        this.jsSecond.setBounds(this.jsMinute.getX() + this.jsMinute.getWidth() + 8 ,this.jsHour.getY() ,this.jsHour.getWidth() ,this.jsHour.getHeight());
        
        
        this.setLayout(null);
        this.setSize(v_MyWidth ,this.jtTime.getHeight() + this.jsHour.getHeight() + 2);
        this.add(this.jtTime);
        this.add(this.jsHour);
        this.add(this.jsMinute);
        this.add(this.jsSecond);
        
        
        
        // 事件
        this.jsHour  .addAdjustmentListener(new HourListener());
        this.jsMinute.addAdjustmentListener(new MinuteListener());
        this.jsSecond.addAdjustmentListener(new SecondListener());
    }
    
    
    
    /**
     * 设置小时调整器
     * 
     * @param i_Hour
     */
    protected void setHour(int i_Hour)
    {
        this.setValue(i_Hour ,this.minute ,this.second);
    }
    
    
    
    /**
     * 设置分钟调整器
     * 
     * @param i_Hour
     */
    protected void setMinute(int i_Minute)
    {
        this.setValue(this.hour ,i_Minute ,this.second);
    }
    
    
    
    /**
     * 设置秒钟调整器
     * 
     * @param i_Second
     */
    protected void setSecond(int i_Second)
    {
        this.setValue(this.hour ,this.minute ,i_Second);
    }
    
    
    
    /**
     * 设置时刻面板的值
     * 
     * @param i_Date  java.util.Date
     */
    public void setValue(java.util.Date i_Date)
    {
        if ( i_Date == null )
        {
            return;
        }
        
        this.setValue(new Date(i_Date));
    }
    
    
    
    /**
     * 设置时刻面板的值
     * 
     * @param i_Date  org.hy.common.Date
     */
    public void setValue(Date i_Date)
    {
        if ( i_Date == null )
        {
            return;
        }
        
        this.setValue(i_Date.getHours() ,i_Date.getMinutes() ,i_Date.getSeconds());
    }
    
    
    
    /**
     * 设置时刻面板的值
     * 
     * @param i_Date
     */
    public void setValue(int i_Hour ,int i_Minute ,int i_Second)
    {
        if ( 0> i_Hour || i_Hour > 23 )
        {
            return;
        }
        
        if ( 0> i_Minute || i_Minute > 59 )
        {
            return;
        }
        
        if ( 0> i_Second || i_Second > 59 )
        {
            return;
        }
        
        
        this.isAllowEvent = false;
        boolean v_IsFireEvent = (this.hour != i_Hour) || (this.minute != i_Minute) || (this.second != i_Second);
        
        this.hour   = i_Hour;
        this.minute = i_Minute;
        this.second = i_Second;
        
        
        // " 00  :  00  :  00 "
        StringBuilder v_Buffer = new StringBuilder();
        
        v_Buffer.append(" ");
        if ( this.hour < 10 )
        {
            v_Buffer.append("0");
        }
        v_Buffer.append(this.hour);
        v_Buffer.append("  :  ");
        if ( this.minute < 10 )
        {
            v_Buffer.append("0");
        }
        v_Buffer.append(this.minute);
        v_Buffer.append("  :  ");
        if ( this.second < 10 )
        {
            v_Buffer.append("0");
        }
        v_Buffer.append(this.second);
        v_Buffer.append(" ");
        
        this.jtTime  .setText(v_Buffer.toString());
        this.jsHour  .setValue(i_Hour);
        this.jsMinute.setValue(i_Minute);
        this.jsSecond.setValue(i_Second);
        
        this.isAllowEvent = true;
        
        if ( v_IsFireEvent )
        {
            this.fireTimeChange();
        }
    }
    
    
    
    /**
     * 获取小时
     * 
     * @return
     */
    public int getHour()
    {
        return this.hour;
    }
    
    
    
    /**
     * 获取分钟
     * 
     * @return
     */
    public int getMinute()
    {
        return this.minute;
    }
    
    
    
    /**
     * 获取秒钟
     * 
     * @return
     */
    public int getSecond()
    {
        return this.second;
    }
    
    
    
    /**
     * 小时调节器的事件
     */
    class HourListener implements AdjustmentListener
    {
        
        @Override
        public void adjustmentValueChanged(AdjustmentEvent e)
        {
            if ( isAllowEvent )
            {
                if ( e.getValue() == -1 )
                {
                    jsHour.setValue(23);
                    return;
                }
                else if ( e.getValue() == 24 )
                {
                    jsHour.setValue(0);
                    return;
                }
                
                setHour(e.getValue());
            }
        }
        
    }
    
    
    
    /**
     * 分钟调节器的事件
     */
    class MinuteListener implements AdjustmentListener
    {
        
        @Override
        public void adjustmentValueChanged(AdjustmentEvent e)
        {
            if ( isAllowEvent )
            {
                if ( e.getValue() == -1 )
                {
                    jsMinute.setValue(59);
                    return;
                }
                else if ( e.getValue() == 60 )
                {
                    jsMinute.setValue(0);
                    return;
                }
                
                setMinute(e.getValue());
            }
        }
        
    }
    
    
    
    /**
     * 秒钟调节器的事件
     */
    class SecondListener implements AdjustmentListener
    {
        
        @Override
        public void adjustmentValueChanged(AdjustmentEvent e)
        {
            if ( isAllowEvent )
            {
                if ( e.getValue() == -1 )
                {
                    jsSecond.setValue(59);
                    return;
                }
                else if ( e.getValue() == 60 )
                {
                    jsSecond.setValue(0);
                    return;
                }
                
                setSecond(e.getValue());
            }
        }
        
    }
    
}
